
-- Some stuff (LibBars handling, positioning) taken from Heatsink/HotCandy

local function print(message) DEFAULT_CHAT_FRAME:AddMessage("|cff33ff99Wheel:|r "..tostring(message)) end

Wheel = LibStub("AceAddon-3.0"):NewAddon("Wheel", "AceEvent-3.0", "AceConsole-3.0", "AceTimer-3.0")

local Candy = LibStub("LibCandyBar-3.0")

--------------------------------------------------------------------------------
-- Helpers - from Yatba
--------------------------------------------------------------------------------

function Wheel.erase(...)
	for i=1, select('#', ...) do
		local t = select(i, ...)
		local mt = getmetatable(t)
		setmetatable(t, nil)
		for k in pairs(t) do
			t[k] = nil
		end
		setmetatable(t, mt)
	end
end

do
	local list = setmetatable({}, {__mode='k'})
	function Wheel.new(...)
		local t = next(list)
		if t then
			list[t] = nil
			for i = 1, select('#', ...) do
				t[i] = select(i, ...)
			end
			return t
		else
			return {...}
		end
	end
	function Wheel.del(t)
		if type(t) == 'table' then
			setmetatable(t, nil)
			for k in pairs(t) do
				t[k] = nil
			end
			list[t] = true
		end
		return nil
	end
end

-- Courtesy of AceDB-2.0
local function copyTable(to, from)
	setmetatable(to, nil)
	for k,v in pairs(from) do
		if type(k) == "table" then
			k = copyTable({}, k)
		end
		if type(v) == "table" then
			v = copyTable({}, v)
		end
		to[k] = v
	end
	setmetatable(to, from)
	return to
end
Wheel.copyTable = copyTable


local GUID = LibStub("LibGUIDRegistry-0.1")
local LSM = LibStub("LibSharedMedia-3.0")
local AceConfig = LibStub("AceConfig-3.0")
local AceConfigRegistry = LibStub("AceConfigRegistry-3.0")
local AceConfigDialog = LibStub("AceConfigDialog-3.0")

local LSM_Fonts = {}
local LSM_Textures = {}

local defaults = {
	profile = {
		enablezone = {
			world = false,
			bg = false,
			arena = false,
			partyinstance = false,
			raidinstance = true,
		},
		announces = {
			general = {
				enablezone = {
					world = false,
					bg = false,
					arena = false,
					partyinstance = false,
					raidinstance = true,
				},
				channels = {
					group = true,
					whisper = nil,
				},
				messages = {
					start = ">>> $s up <<<",
					finish = ">>> $s ends <<<",
					whisper = ">>> $s on you <<<",
				},
			},
			map = {
			},
			rules = {
			},
		},
		groups = {
		},
		group_defaults = {
			width = 180,
			height = 15,
			fontsize = 8,
			scale = 1,
			buff_r = 0,
			buff_g = 1,
			buff_b = 0,
			buff_a = 1,
			debuff_r = 1,
			debuff_g = 0,
			debuff_b = 0,
			debuff_a = 1,
			cooldown_r = 0,
			cooldown_g = 0,
			cooldown_b = 1,
			cooldown_a = 1,
			label = "$c",
		},
		general = {
			lock = true,
			texture = "Minimalist",
			font = "Emblem",
			colour = {
				r = 0,
				g = 0.5,
				b = 1,
			},
		},
		pulse = {
			duration = 1,
			warning = 5,
			max_width = 100,
			min_width = 75,
			x = 0,
			y = 0,
		},

		announce = false,
--		testduration = 3,
	},
}


---------------------------------
--   Widget creation helpers   --
---------------------------------

local function createToggle(name, getFunction, setFunction, order, width)
	return {
		type = "toggle",
		name = name,
		desc = name,
		get = getFunction,
		set = setFunction,
		order = order,
		width = width,
	}
end

local function createRange(name, getFunction, setFunction, order, min, max, step, isPercent)
	return {
		type = "range",
		name = name,
		desc = name,
		get = getFunction,
		set = setFunction,
		order = order,
		min = min,
		max = max,
		step = step or 1,
		isPercent = isPercent,
	}
end

local function createSelect(name, getFunction, setFunction, order, values)
	return {
		type = "select",
		name = name,
		desc = name,
		get = getFunction,
		set = setFunction,
		order = order,
		values = values or {},
	}
end

local function createLSMSelect(name, getFunction, setFunction, order, values, dialogControl)
	return {
		type = "select",
		name = name,
		desc = name,
		get = getFunction,
		set = setFunction,
		order = order,
		values = values or {},
		dialogControl = dialogControl,
	}
end

local function createExecute(name, func, order)
	return {
		type = "execute",
		name = name,
		desc = name,
		func = func,
		order = order,
	}
end

local function createInput(name, getFunction, setFunction, order, pattern, width)
	return {
		type = "input",
		name = name,
		desc = name,
		get = getFunction,
		set = setFunction,
		order = order,
		pattern = pattern or "%w+",
		width = width,
	}
end

local function createColour(name, getFunction, setFunction, order)
	return {
		type = "color",
		name = name,
		desc = name,
		get = getFunction,
		set = setFunction,
		order = order,
		hasAlpha = true,
	}
end

local function createDescription(name, order)
	return {
		type = "description",
		name = name,
		order = order,
	}
end

local function createHeader(name, order)
	return {
		type = "header",
		name = name,
		order = order,
	}
end


local function getAnnounceOption(info)
	local name = info[#info - 1]
	local option = info[#info]
	return Wheel.db.profile.announces.rules[name][option]
end

local function setAnnounceOption(info, v)
	local name = info[#info - 1]
	local option = info[#info]
	Wheel.db.profile.announces.rules[name][option] = v
end

local function getGroupDefaultOption(info)
	local option = info[#info]
	return Wheel.db.profile.group_defaults[option]
end

local function setGroupDefaultOption(info, v)
	local option = info[#info]
	Wheel.db.profile.group_defaults[option] = v
end

local function getGroupOption(info)
	local group = info[#info - 1]
	local option = info[#info]
	return Wheel.db.profile.groups[group][option]
end

local function setGroupOption(info, v)
	local group = info[#info - 1]
	local option = info[#info]
	Wheel.db.profile.groups[group][option] = v

	Wheel:ApplySettings(group)
end

local function getValidChannelList()
	local channels = Wheel:GetCustomChannelList()

	channels["RAID"] = "Raid"
	channels["PARTY"] = "Party"
	channels["SAY"] = "Say"
	channels["YELL"] = "Yell"
	channels["WHISPER"] = "Whisper"

	return channels
end

local function getAnnounceGeneralOption(info)
	local group = info[#info - 1]
	local option = info[#info]
	return Wheel.db.profile.announces.general[group][option]
end

local function setAnnounceGeneralOption(info, v)
	local group = info[#info - 1]
	local option = info[#info]
	Wheel.db.profile.announces.general[group][option] = v
end

local function getGeneralChannelList()
	local tbl = {}

	tbl.group = createToggle("Group", getAnnounceGeneralOption, setAnnounceGeneralOption, 27)
	tbl.whisper = createToggle("Whisper", getAnnounceGeneralOption, setAnnounceGeneralOption, 27)
	local channels = Wheel:GetCustomChannelList()
	for channel in pairs(channels) do
		tbl[channel] = createToggle(channel, getAnnounceGeneralOption, setAnnounceGeneralOption, 27)
	end

	return tbl
end

local options = {
  	handler = Wheel,
	type = "group",
--	childGroups = "tab",
	args = {
		spells = {
			type=  "group",
			name = "Spells",
			desc = "Spells",
			args = {
			},
			order = 10,
		},
		enablezone = {
			type= "group",
			name = "Zone",
			desc = "Zone",
			args = {
				world = {
					type = "toggle",
					name = "World",
					desc = "Enable reports in the outside world",
					get = function()
						return Wheel.db.profile.enablezone.world
					end,
					set = function(info, v)
						Wheel.db.profile.enablezone.world = v
						Wheel:CheckEnable()
					end,
					order = 1,
				},
				bg = {
					type = "toggle",
					name = "Battlegrounds",
					desc = "Enable reports in battlegrounds",
					get = function()
						return Wheel.db.profile.enablezone.bg
					end,
					set = function(info, v)
						Wheel.db.profile.enablezone.bg = v
						Wheel:CheckEnable()
					end,
					order = 2,
				},
				arena = {
					type = "toggle",
					name = "Arena",
					desc = "Enable reports in arena",
					get = function()
						return Wheel.db.profile.enablezone.arena
					end,
					set = function(info, v)
						Wheel.db.profile.enablezone.arena = v
						Wheel:CheckEnable()
					end,
					order = 3,
				},
				partyinstance = {
					type = "toggle",
					name = "Party Instances",
					desc = "Enable reports in 5-man instances",
					get = function()
						return Wheel.db.profile.enablezone.partyinstance
					end,
					set = function(info, v)
						Wheel.db.profile.enablezone.partyinstance = v
						Wheel:CheckEnable()
					end,
					order = 4,
				},
				raidinstance = {
					type = "toggle",
					name = "Raid Instances",
					desc = "Enable reports in raid instances",
					get = function()
						return Wheel.db.profile.enablezone.raidinstance
					end,
					set = function(info, v)
						Wheel.db.profile.enablezone.raidinstance = v
						Wheel:CheckEnable()
					end,
					order = 5,
				},
			},
			order = 2,
		},
		groups = {
			type= "group",
			name = "Groups",
			desc = "Groups",
			args = {
				new = {
					name = 'New group',
					desc = 'Create a new bar group.',
					type = "input",
					get = false,
					set = function(info, v)
						Wheel:InitializeGroup(v)
					end,
					pattern = '^%w+$',
					order = 0,
				},
			},
			order = 3,
		},
		announces = {
			type= "group",
			name = "Announces",
			desc = "Announces",
			args = {
				new = {
					name = 'New announce',
					desc = 'Create a new announce.',
					type = "input",
					get = false,
					set = function(info, v)
						Wheel:InitializeAnnounce(v)
					end,
					pattern = '^[%w|%s]+$',
					order = 0,
				},
				header1 = {
					name = "General options",
					type = "header",
					order = 5,
				},
				enablezone = {
					type = "group",
					name = "Zone Settings",
					desc = "Zone Settings",
					inline = true,
					args = {
						world = {
							type = "toggle",
							name = "World",
							desc = "Enable reports in the outside world",
							get = getAnnounceGeneralOption,
							set = setAnnounceGeneralOption,
							order = 10,
						},
						bg = {
							type = "toggle",
							name = "Battlegrounds",
							desc = "Enable reports in battlegrounds",
							get = getAnnounceGeneralOption,
							set = setAnnounceGeneralOption,
							order = 11,
						},
						arena = {
							type = "toggle",
							name = "Arena",
							desc = "Enable reports in arena",
							get = getAnnounceGeneralOption,
							set = setAnnounceGeneralOption,
							order = 12,
						},
						partyinstance = {
							type = "toggle",
							name = "Party Instances",
							desc = "Enable reports in 5-man instances",
							get = getAnnounceGeneralOption,
							set = setAnnounceGeneralOption,
							order = 13,
						},
						raidinstance = {
							type = "toggle",
							name = "Raid Instances",
							desc = "Enable reports in raid instances",
							get = getAnnounceGeneralOption,
							set = setAnnounceGeneralOption,
							order = 14,
						},
					},
					order = 10,
				},
				channels = {
					type = "group",
					name = "Channel Settings",
					desc = "Channel Settings",
					inline = true,
					args = {},
					order = 20,
				},
				messages = {
					type = "group",
					name = "Messages",
					desc = "Messages",
					inline = true,
					args = {
						start = createInput("Start", getAnnounceGeneralOption, setAnnounceGeneralOption, 10, nil, "full"),
						finish = createInput("Finish", getAnnounceGeneralOption, setAnnounceGeneralOption, 20, nil, "full"),
						whisper = createInput("Whisper", getAnnounceGeneralOption, setAnnounceGeneralOption, 30, nil, "full"),
					},
					order = 30,
				},
			},
			order = 4,
		},
		pulse = {
			type= "group",
			name = "Pulse",
			desc = "Pulse",
			args = {
				maxwidth = {
					type = "range",
					name = "Maximum width",
					desc = "Maximum width",
					get = function()
						return Wheel.db.profile.pulse.max_width
					end,
					set = function(info, v)
						Wheel.db.profile.pulse.max_width = v
					end,
					min = 10,
					max = 200,
					step = 1,
					isPercent = false,
					order = 1,
				},
				minwidth = {
					type = "range",
					name = "Minimum width",
					desc = "Minimum width",
					get = function()
						return Wheel.db.profile.pulse.min_width
					end,
					set = function(info, v)
						Wheel.db.profile.pulse.min_width = v
					end,
					min = 10,
					max = 200,
					step = 1,
					isPercent = false,
					order = 2,
				},
				duration = {
					type = "range",
					name = "Duration",
					desc = "Duration",
					get = function()
						return Wheel.db.profile.pulse.duration
					end,
					set = function(info, v)
						Wheel.db.profile.pulse.duration = v
					end,
					min = 1,
					max = 10,
					step = 1,
					isPercent = false,
					order = 3,
				},
				x = {
					type = "range",
					name = "Horizontal offset",
					desc = "Horizontal Offset",
					get = function()
						return Wheel.db.profile.pulse.x
					end,
					set = function(info, v)
						Wheel.db.profile.pulse.x = v
					end,
					min = 0,
					max = 1000,
					step = 1,
					isPercent = false,
					order = 4,
				},
				y = {
					type = "range",
					name = "Vertical offset",
					desc = "Vertical Offset",
					get = function()
						return Wheel.db.profile.pulse.y
					end,
					set = function(info, v)
						Wheel.db.profile.pulse.y = v
					end,
					min = 0,
					max = 1000,
					step = 1,
					isPercent = false,
					order = 5,
				},
				warning = {
					type = "range",
					name = "Expiry warning",
					desc = "Expiry warning",
					get = function()
						return Wheel.db.profile.pulse.warning
					end,
					set = function(info, v)
						Wheel.db.profile.pulse.warning = v
					end,
					min = 0,
					max = 10,
					step = 1,
					isPercent = false,
					order = 6,
				},
			},
			order = 5,
		},
	},
}

local function addMenuOptions(group, isDefault)
	local group = group

	local getFunction = getGroupOption
	local setFunction = setGroupOption
	if isDefault then
		getFunction = getGroupDefaultOption
		setFunction = setGroupDefaultOption
	end

	local table = {}

	table.lock = createToggle("Show Anchor", getFunction, setFunction, 1)

	if not isDefault then
		table.testrun = {
			type = "execute",
			name = "Test",
			desc = "Test bars",
			func = function()
				Wheel:Test(group)
			end,
			order = 2,
		}
	end

	table.header1 = createHeader("", 10)

	table.width = createRange("Bar Width", getFunction, setFunction, 11, 20, 500, 5, nil)
	table.height = createRange("Bar Height", getFunction, setFunction, 12, 5, 50, 1, nil)
	table.scale = createRange("Bar Scale", getFunction, setFunction, 13, 0.5, 5, 0.1, true)
	table.growth = createToggle("Grow Up", getFunction, setFunction, 14)

	table.header2 = createHeader("", 20)

	createLSMSelect("Texture", getFunction, setFunction, 21, LSM_Textures, "LSM30_Statusbar")
	createLSMSelect("Font", getFunction, setFunction, 22, LSM_Fonts, "LSM30_Font")
	table.fontsize = createRange("Font Size", getFunction, setFunction, 23, 7, 48, 1, nil)

	table.header3 = createHeader("", 30)

	table.flash = createToggle("Flash", getFunction, setFunction, 32)

	table.header4 = createHeader("", 40)

	table.label = createInput("Label", getFunction, setFunction, 45, nil, "full")

	return table
end

local function addGroupOptions(group, name)
	options.args.groups.args[group] = {
		type = "group",
		name = name,
		desc = name,
		args = addMenuOptions(group),
	}
end

local function getAnnounceRuleOption(info)
	local rule = info[#info - 2]
	local group = info[#info - 1]
	local option = info[#info]
	return Wheel.db.profile.announces.rules[rule][group][option]
end

local function setAnnounceRuleOption(info, v)
	local rule = info[#info - 2]
	local group = info[#info - 1]
	local option = info[#info]
	Wheel.db.profile.announces.rules[rule][group][option] = v
end

local function getAnnounceChannelOption(info)
	local rule = info[#info - 2]
	local option = info[#info]
	return Wheel.db.profile.announces.rules[rule][option]
end

local function setAnnounceChannelOption(info, v)
	local rule = info[#info - 2]
	local option = info[#info]
	Wheel.db.profile.announces.rules[rule][option] = v
end

local function test(info)
	Wheel:DeleteAnnounce(info[#info - 1])
end

local function addAnnounceMenuOptions(name, isDefault)
	local name = name

	local getFunction = getAnnounceOption
	local setFunction = setAnnounceOption
--	if isDefault then
--		getFunction = getGroupDefaultOption
--		setFunction = setGroupDefaultOption
--	end

	local table = {}

	table.enable = createToggle("Enable", getFunction, setFunction, 5)

	table.delete = createExecute("Delete", test, 6)

	table.header1 = createHeader("Zone settings", 10)

	table.usegeneralenable = createToggle("Use general zone settings", getFunction, setFunction, 15, "full")

	local enabletbl = {}
	enabletbl.type = "group"
	enabletbl.name = "Zone"
	enabletbl.desc = "Zone"
	enabletbl.inline = true
	enabletbl.args = {}
	enabletbl.args.world = createToggle("World", getAnnounceRuleOption, setAnnounceRuleOption, 20)
	enabletbl.args.bg = createToggle("Battlegrounds", getAnnounceRuleOption, setAnnounceRuleOption, 21)
	enabletbl.args.arena = createToggle("Arena", getAnnounceRuleOption, setAnnounceRuleOption, 22)
	enabletbl.args.partyinstance = createToggle("Party Instances", getAnnounceRuleOption, setAnnounceRuleOption, 23)
	enabletbl.args.raidinstance = createToggle("Raid Instances", getAnnounceRuleOption, setAnnounceRuleOption, 24)
	enabletbl.hidden = function() return Wheel.db.profile.announces.rules[name].usegeneralenable end
	enabletbl.order = 20

	table.enablezone = enabletbl

	table.header2 = createHeader("Channels", 30)

	-- Channel

	table.usegeneralchannels = createToggle("Use general channels", getFunction, setFunction, 35, "full")

	local channelstbl = {}
	channelstbl.type = "group"
	channelstbl.name = "Channels"
	channelstbl.desc = "Channels"
	channelstbl.inline = true
	channelstbl.args = {}
	channelstbl.args.group = createToggle("Group", getAnnounceRuleOption, setAnnounceRuleOption, 10)
	channelstbl.args.whisper = createToggle("Whisper", getAnnounceRuleOption, setAnnounceRuleOption, 20)
	local order = 30
	local channels = Wheel:GetCustomChannelList()
	for channel in pairs(channels) do
		channelstbl.args[channel] = createToggle(channel, getAnnounceRuleOption, setAnnounceRuleOption, order)
		order = order + 10
	end
	channelstbl.hidden = function() return Wheel.db.profile.announces.rules[name].usegeneralchannels end
	channelstbl.order = 36

	table.channels = channelstbl

	table.header3 = createHeader("Channels", 40)

	-- Messages

	table.usegeneralmessages = createToggle("Use general messages", getFunction, setFunction, 45, "full")

	local messagestbl = {}
	messagestbl.type = "group"
	messagestbl.name = "Messages"
	messagestbl.desc = "Messages"
	messagestbl.inline = true
	messagestbl.args = {}
	messagestbl.args.start = createInput("Start", getAnnounceRuleOption, setAnnounceRuleOption, 10, nil, "full")
	messagestbl.args.finish = createInput("Finish", getAnnounceRuleOption, setAnnounceRuleOption, 20, nil, "full")
	messagestbl.args.whisper = createInput("Whisper", getAnnounceRuleOption, setAnnounceRuleOption, 20, nil, "full")
	messagestbl.hidden = function() return Wheel.db.profile.announces.rules[name].usegeneralmessages end
	messagestbl.order = 46

	table.messages = messagestbl

--	table.header4 = createHeader("", 50)

	return table
end

function Wheel:AddAnnounceOptions(name)
	options.args.announces.args[name] = {
		type = "group",
		name = name,
		desc = name,
		args = addAnnounceMenuOptions(name),
	}
end

function Wheel:DeleteAnnounceOptions(name)
	options.args.announces.args[name] = nil
	AceConfigRegistry:NotifyChange("Wheel")
end

local function getSpellStatus(info)
	return Wheel.db.profile.spells[info[#info]].enabled
end

local function setSpellStatus(info, v)
	Wheel.db.profile.spells[info[#info]].enabled = v
end

local prettyclass = {
	DEATHKNIGHT = "Death Knight",
	DRUID = "Druid",
	HUNTER = "Hunter",
	MAGE = "Mage",
	PALADIN = "Paladin",
	PRIEST = "Priest",
	ROGUE = "Rogue",
	SHAMAN = "Shaman",
	WARLOCK = "Warlock",
	WARRIOR = "Warrior",
	item = "Item",
}

local function addSpellOptions()
	local db = Wheel.db.profile.spells

	local class
	for spellid in pairs(db) do
		class = db[spellid].class
		if not options.args.spells.args[class] then
			local tbl = {}
			tbl.type = "group"
			tbl.name = prettyclass[class]
			tbl.desc = prettyclass[class]
			tbl.args = {}
			options.args.spells.args[class] = tbl
		end
		options.args.spells.args[class].args[tostring(spellid)] = createToggle(db[spellid].name, getSpellStatus, setSpellStatus, 1)
	end
end



function Wheel:OnInitialize()
	self.db = LibStub("AceDB-3.0"):New("WheelDB", defaults, "Default")

	local profiles = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db)
	options.args.profiles = profiles

	AceConfigRegistry:RegisterOptionsTable("Wheel", options)
--	AceConfigRegistry:RegisterOptionsTable("Wheel Profiles", profiles)

	self:RegisterChatCommand("wheel", function()
		options.args.announces.args.channels.args = getGeneralChannelList()
		LibStub("AceConfigDialog-3.0"):Open("Wheel")
	end)

	AceConfigDialog:AddToBlizOptions("Wheel", "Wheel")
	AceConfigDialog:AddToBlizOptions("Wheel Profiles", "Profiles", "Wheel")

	self.db.RegisterCallback(self, "OnProfileChanged", "UpdateProfile")
	self.db.RegisterCallback(self, "OnProfileCopied", "UpdateProfile")
	self.db.RegisterCallback(self, "OnProfileReset", "UpdateProfile")

--	LSM.RegisterCallback(self, "LibSharedMedia_Registered", "UpdateAll")
--	LSM.RegisterCallback(self, "LibSharedMedia_SetGlobal", "UpdateAll")
	LSM:RegisterCallback("LibSharedMedia_Registered", function(event, mediatype, key)
		if mediatype == "font" then
			LSM_Fonts[key] = key
		elseif mediatype == "statusbar" then
			LSM_Textures[key] = key
		end
	end)

	for k, v in pairs(LSM:List("font")) do
		LSM_Fonts[v] = v
	end
	for k, v in pairs(LSM:List("statusbar")) do
		LSM_Textures[v] = v
	end

	for name in pairs(self.db.profile.groups) do
		self:InitializeGroup(name)
	end

	for rule in pairs(self.db.profile.announces.rules) do
		print("Announce: "..rule)
		self:InitializeAnnounce(rule)
	end

	-- FIXME: temporary until proper configuration in place
--	self:DummyGroupInit()
	self:DummyInit()

	addSpellOptions()

	self:UpdateLock()

--	self:SetGroupColours()

	self:CreatePulse()
end

function Wheel:OnEnable()
	self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")

	self:RegisterEvent("PLAYER_ENTERING_WORLD", "UpdateRoster")
	self:RegisterEvent("PARTY_MEMBERS_CHANGED", "UpdateRoster")
	self:RegisterEvent("RAID_ROSTER_UPDATE", "UpdateRoster")
	self:RegisterEvent("PLAYER_FOCUS_CHANGED")
	self:RegisterEvent("PLAYER_TARGET_CHANGED")

	Candy.RegisterCallback(self, "LibCandyBar_Stop", "BarStopped")

	self:UpdateRoster()
end

function Wheel:OnDisable()
	self:UnregisterAllEvents()
end

-----------------------
--   Bars handling   --
-----------------------

function Wheel:InitializeGroup(name)
	local db = self.db.profile

	group = name

	if not db.groups[group] then
		db.groups[group] = {}
	end

	for k, v in pairs(db.group_defaults) do
		if not db.groups[group][k] then
			db.groups[group][k] = v
		end
	end

	addGroupOptions(group, name)

	self:CreateAnchor(group)
	
--	self:ApplySettings(group)
	self:UpdateLock()
end

function Wheel:IntializePlayerGroup()
	
end

function Wheel:SetRuleGroup(group, ruletype, rule)
	self.db.profile.groups[group][ruletype] = rule
end

function Wheel:UpdateProfile()
--	self:UpdateAll()
	self:UpdateLock()
end

function Wheel:UpdateLock()
	for group in pairs(self.anchor) do
		if self.db.profile.groups[group].lock then
			self.anchor[group]:Show()
		else
			self.anchor[group]:Hide()
		end
	end
end

function Wheel:Test(group)
	self:StartBar(group, "Paladin1", "PALADIN", 31821, "Paladin1", "Paladin1", 30)
	self:StartBar(group, "Priest", "PRIEST", 47788, "Priest", "Priest", 20)
	self:StartBar(group, "Paladin2", "PALADIN", 6940, "Paladin2", "Paladin2", 10)
end

------------------------
--   Event handling   --
------------------------

function Wheel:IsValidZone(db)
	local i, t = IsInInstance()

	local match
	if i then
		if t == "pvp" and db.bg then
			match = true
		elseif t == "arena" and db.arena then
			match = true
		elseif t == "party" and db.partyinstance then
			match = true
		elseif t == "raid" and db.raidinstance then
			match = true
		end
	else
		if db.world then
			match = true
		end
	end

	return match
end

--[[function Wheel:CheckEnable()
	local i, t = IsInInstance()
	local enable

	local db = self.db.profile.enablezone
	if i then
		if t == "pvp" and db.bg then
			enable = true
		elseif t == "arena" and db.arena then
			enable = true
		elseif t == "party" and db.partyinstance then
			enable = true
		elseif t == "raid" and db.raidinstance then
			enable = true
		end
	else
		if db.world then
			enable = true
		end
	end

	if enable then
		self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
	else
		self:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
	end
end
]]
function Wheel:EventSpellCastSuccess(id, guid, name)
	print("Cooldown: "..id.." : "..guid.." : "..name)
	class = GUID:GetClass(guid)
--	self:StartBar("cooldownview", name, class, id, spells[id].cooldown)
end

function Wheel:PrintAnnounce(message, channel, target)
	if channel == "group" then
		if GetNumRaidMembers() > 0 then
			SendChatMessage(message, "RAID")
		elseif GetNumPartyMembers() > 0 then
			SendChatMessage(message, "PARTY")
		end
	elseif channel == "whisper" then
		SendChatMessage(message, "WHISPER", nil, target)
	else
		local index = self:GetChatChannelIndex(channel)
		if index then
			SendChatMessage(message, "CHANNEL", nil, index)
		end
	end
end

function Wheel:AnnounceStart(spellid, sourceName, targetName)
--	print("AnnounceStart "..spellid)
	local rule = self.db.profile.announces.map[spellid]
	if rule then
		local db = self.db.profile.announces.rules[rule]

		if not db.enable then
			return
		end

		local enabledb
		if db.usegeneralenable then
			enabledb = self.db.profile.announces.general.enablezone
		else
			enabledb = db.enablezone
		end
		if not self:IsValidZone(enabledb) then
			return
		end

		local announce
		if db.usegeneralmessages then
			announce = self.db.profile.announces.general.messages.start
			whisper = self.db.profile.announces.general.messages.whisper
		else
			announce = db.messages.start
			whisper = db.messages.whisper
		end

		local channels
		if db.usegeneralchannels then
			channels = self.db.profile.announces.general.channels
		else
			channels = db.channels
		end

		local text
		if announce then
			text = string.gsub(announce, "$t", targetName)
			text = string.gsub(text, "$c", sourceName)
			text = string.gsub(text, "$s", self.db.profile.spells[spellid].name)
			for k, v in pairs(channels) do
				if v and k ~= "whisper" then
					self:PrintAnnounce(text, k, targetName)
				end
			end
		end
		if whisper and channels.whisper then
			text = string.gsub(whisper, "$t", targetName)
			text = string.gsub(text, "$c", sourceName)
			text = string.gsub(text, "$s", self.db.profile.spells[spellid].name)
			self:PrintAnnounce(text, "whisper", targetName)
		end
	end
end

function Wheel:AnnounceEnd(spellid, targetName)
	local rule = self.db.profile.announces.map[spellid]
	if rule then
		local db = self.db.profile.announces.rules[rule]

		if not db.enable then
			return
		end

		local enabledb
		if db.usegeneralenable then
			enabledb = self.db.profile.announces.general.enablezone
		else
			enabledb = db.enablezone
		end
		if not self:IsValidZone(enabledb) then
			return
		end

		local announce
		if db.usegeneralmessages then
			announce = self.db.profile.announces.general.messages.finish
		else
			announce = db.messages.finish
		end

		local text
		if announce then
			text = string.gsub(announce, "$t", targetName)
			text = string.gsub(text, "$c", sourceName)
			text = string.gsub(text, "$s", self.db.profile.spells[spellid].name)
			local channels
			if db.usegeneralchannels then
				channels = self.db.profile.announces.general.channels
			else
				channels = db.channels
			end
			for k, v in pairs(channels) do
				if v and k ~= "whisper" then
					self:PrintAnnounce(text, k, targetName)
				end
			end
		end
	end
end

function Wheel:EventSpellAuraApplied(id, sourceGUID, sourceName, targetGUID, targetName)
--	print("EventSpellAuraApplied: "..id)
	local db = self.db.profile
	-- FIXME: this is run even when duration not needed (?)
	local guid = targetGUID
	local name = targetName
	if db.spells[id].trackSelf then
		guid = sourceGUID
		name = sourceName
	end
	if not self:RosterIsInRaid(guid) then return end

	local duration = self:UnitHasBuff(guid, id)
	if duration then
		local sourceid = self:RosterGetUnitID(sourceGUID)
		local targetid = self:RosterGetUnitID(targetGUID)
		local index
--		for group in pairs(db.spells[id].aura_groups) do
		for group in pairs(db.groups) do
			index = self:ValidateRule(group, id, sourceid, sourceName, targetid, targetName)
			if index then
				self:StartBar(group, id, sourceGUID, sourceName, targetGUID, targetName, duration, index)
			end
		end

		if sourceid == "player" and (not db.spells[id].trackSelf or (db.spells[id].trackSelf and targetid == "player")) then
			self:AnnounceStart(id, sourceName, targetName)
		end
	else
		print("Buff: "..id.." : "..guid.." : "..name)
		print("Duration unknown")
	end
end

function Wheel:EventSpellAuraRefresh(id, sourceGUID, sourceName, targetGUID, targetName)
	local db = self.db.profile
	-- FIXME: this is run even when duration not needed (?)
	local guid = targetGUID
	local name = targetName
	if db.spells[id].trackSelf then
		guid = sourceGUID
		name = sourceName
	end
	if not self:RosterIsInRaid(guid) then return end

	local duration = self:UnitHasBuff(guid, id)
	if duration then
		local sourceid = self:RosterGetUnitID(sourceGUID)
		local targetid = self:RosterGetUnitID(targetGUID)
		local index
--		for group in pairs(db.spells[id].aura_groups) do
		for group in pairs(db.groups) do
			index = self:ValidateRule(group, id, sourceid, sourceName, targetid, targetName)
			if index then
				self:RefreshBar(group, id, sourceGUID, sourceName, targetGUID, targetName, duration, index)
			end
		end

		if sourceid == "player" and (not db.spells[id].trackSelf or (db.spells[id].trackSelf and targetid == "player")) then
			self:AnnounceStart(id, sourceName, targetName)
		end
	else
		print("Buff: "..id.." : "..guid.." : "..name)
		print("Duration unknown")
	end
end

function Wheel:EventSpellAuraRemoved(id, sourceGUID, sourceName, targetGUID, targetName)
--	print("Buff off: "..id.." : "..sourceName.." : "..targetName)
	local db = self.db.profile
	-- FIXME: this is run even when duration not needed (?)
	local guid = targetGUID
	local name = targetName
	if db.spells[id].trackSelf then
		guid = sourceGUID
		name = sourceName
	end
	if not self:RosterIsInRaid(guid) then return end

	local sourceid = self:RosterGetUnitID(sourceGUID)
	local targetid = self:RosterGetUnitID(targetGUID)
--	for group in pairs(db.spells[id].aura_groups) do
	for group in pairs(db.groups) do
--		print("group "..group)
--		if self:ValidateRule(sourceUnitID, db.groups[group].spells[id].rule_source) and self:ValidateRule(targetUnitID, db.groups[group].spells[id].rule_target) then
			self:StopBar(group, id, sourceName, targetName, duration)
--		end
	end
	
	if sourceid == "player" and (not db.spells[id].trackSelf or (db.spells[id].trackSelf and targetid == "player")) then
		self:AnnounceEnd(id, targetName)
	end
end

function Wheel:COMBAT_LOG_EVENT_UNFILTERED(_, timestamp, event, sourceGUID, sourceName, sourceFlags, targetGUID, targetName, targetFlags, spellID, spellName)
--	print("CLEU: "..event.." - "..spellName.." ("..spellID..") "..sourceName.." -> "..targetName)
	spellid = tostring(spellID)
	local spell = self.db.profile.spells[spellid]
	if not spell or not spell.enabled then return end

	if event == "SPELL_CAST_SUCCESS" and self:RosterIsInRaid(sourceGUID) then
		if spell.cooldown_groups then
			self:EventSpellCastSuccess(spellid, sourceGUID, sourceName)
		end
	elseif event == "SPELL_AURA_APPLIED" or event == "SPELL_AURA_APPLIED_DOSE" then
--		print("+++ SPELL_AURA_APPLIED: "..spellID.." - "..spellName)
--		if spell.aura_groups then
			self:EventSpellAuraApplied(spellid, sourceGUID, sourceName, targetGUID, targetName)
--		end
	elseif event == "SPELL_AURA_REFRESH" then
--		print("SPELL_AURA_REFRESH: "..spellID.." - "..spellName)
--		if spell.aura_groups then
			self:EventSpellAuraRefresh(spellid, sourceGUID, sourceName, targetGUID, targetName)
--		end
	elseif event == "SPELL_AURA_REMOVED" then
--		print("SPELL_AURA_REMOVED: "..spellID.." - "..spellName)
--		if spell.aura_groups then
			self:EventSpellAuraRemoved(spellid, sourceGUID, sourceName, targetGUID, targetName)
--		end
	end

end

function Wheel:UnitHasBuff(guid, spellID)
	local spell = GetSpellInfo(spellID)
	local unitid = Wheel:RosterGetUnitID(guid)
	local buff, duration
	for i = 1, 40 do
		buff, _, _, _, _, duration = UnitAura(unitid, i, "HELPFUL")
		if not buff or buff == spell then
			break
		end
	end

	return (buff == spell) and duration
end

function Wheel:PLAYER_FOCUS_CHANGED()
	self:UpdateRoster()
end

function Wheel:PLAYER_TARGET_CHANGED()
--[[
	print("target changed")
	local targetGUID = UnitGUID("target")
	local sourceid, sourceName, sourceGUID
	local id
	for i = 1, 40 do
		_, _, _, _, _, _, _, sourceid, _, _, id = UnitAura("target", i, "HELPFUL")
		if not id then
			break
		end
		sourceName = UnitName(sourceid)
		if sourceName then
			print("* "..sourceName.." : "..id)
			sourceGUID = UnitGUID(sourceid)
			if sourceGUID then
				self:EventSpellAuraApplied(tostring(id), sourceGUID, sourceName, targetGUID, UnitName("target"))
			end
		end
	end
]]
	self:UpdateRoster()
end

----------------------
--   Roster stuff   --
----------------------

-- inspired by Grid

do
	-- let's not care about realm for now
	local roster = {
		name = {},
		unitid = {},
	}
	local units_to_remove = {}

	local function UpdateUnit(unit)
		if unit and UnitExists(unit) then
			local name = UnitName(unit)
			local guid = UnitGUID(unit)

			units_to_remove[guid] = nil

			roster.name[guid] = name
			roster.unitid[guid] = unit
		end
	end

	function Wheel:UpdateRoster()
		for guid, unit in pairs(roster.unitid) do
			units_to_remove[guid] = true
		end

		local preffix, n
		if GetNumRaidMembers() == 0 then
			n = 5
			preffix = "party"
		else
			n = 40
			preffix = "raid"
		end

		for i = 1, n do
			UpdateUnit(preffix..tostring(i))
		end

		UpdateUnit("player")
		UpdateUnit("target")
		UpdateUnit("focus")
		UpdateUnit("boss1")
		UpdateUnit("boss2")
		UpdateUnit("boss3")
		UpdateUnit("boss4")
		UpdateUnit("boss5")

		for guid in pairs(units_to_remove) do
			roster.name[guid] = nil
			roster.unitid[guid] = nil
		end
	end

	function Wheel:RosterIsInRaid(guid)
		return roster.unitid[guid] and true or false
	end

	function Wheel:RosterGetUnitID(guid)
		return roster.unitid[guid]
	end

	function Wheel:RosterGetName(guid)
		return roster.name[guid]
	end

	function Wheel:RosterGetGUID(name)
		local guid

		for k, v in pairs(roster.name) do
			if v == name then
				guid = k
				break
			end
		end

		return guid
	end
end

--------------------------------------------------------------------------------
-- Anchors
--

local normalAnchor, emphasizeAnchor

local function barSorter(a, b)
	return a.remaining < b.remaining and true or false
end

local tmp = {}
local function rearrangeBars(anchor)
	wipe(tmp)
	for bar in pairs(anchor.bars) do
		tmp[#tmp + 1] = bar
	end
	table.sort(tmp, barSorter)
	local lastDownBar, lastUpBar = nil, nil
	local up = nil
	for i, bar in next, tmp do
		bar:ClearAllPoints()
		bar:SetPoint("TOPLEFT", lastDownBar or anchor, "BOTTOMLEFT")
		bar:SetPoint("TOPRIGHT", lastDownBar or anchor, "BOTTOMRIGHT")
		lastDownBar = bar
	end
end

local function onDragHandleMouseDown(self)
	self:GetParent():StartSizing("BOTTOMRIGHT")
end

local function onDragHandleMouseUp(self, button)
	self:GetParent():StopMovingOrSizing()
end

local function onResize(self, width)
	Wheel.db.profile.groups[self.group].width = width
	rearrangeBars(self)
end

local function onDragStart(self)
	self:StartMoving()
end

local function onDragStop(self)
	self:StopMovingOrSizing()
	local s = self:GetEffectiveScale()
	Wheel.db.profile.groups[self.group].anchor_x = self:GetLeft() * s
	Wheel.db.profile.groups[self.group].anchor_y = self:GetTop() * s
end

local function onControlEnter(self)
	GameTooltip:ClearLines()
	GameTooltip:SetOwner(self, "ANCHOR_TOPLEFT")
	GameTooltip:AddLine(self.tooltipHeader)
	GameTooltip:AddLine(self.tooltipText, 1, 1, 1, 1)
	GameTooltip:Show()
end

local function onControlLeave()
	GameTooltip:Hide()
end

function Wheel:CreateAnchor(group)
	print("CreateAnchor: "..group)
	if not self.anchor then
		self.anchor = {}
	end

	local db = Wheel.db.profile.groups[group]

	local display = CreateFrame("Frame", "Wheel_"..group, UIParent)
	display:EnableMouse(true)
	display:SetClampedToScreen(true)
	display:SetMovable(true)
	display:SetResizable(true)
	display:RegisterForDrag("LeftButton")
	display:SetWidth(db.width or 200)
	display:SetHeight(20)
	display:SetMinResize(80, 20)
	display:SetMaxResize(1000, 20)
	display:ClearAllPoints()
	if db.anchor_x and db.anchor_y then
		local s = display:GetEffectiveScale()
		display:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", db.anchor_x / s, db.anchor_y / s)
	else
		display:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
	end
	local bg = display:CreateTexture(nil, "PARENT")
	bg:SetAllPoints(display)
	bg:SetBlendMode("BLEND")
	bg:SetTexture(0, 0, 0, 0.3)
	display.background = bg
	local header = display:CreateFontString(nil, "OVERLAY")
	header:SetFontObject(GameFontNormal)
	header:SetText("Wheel "..group)
	header:SetAllPoints(display)
	header:SetJustifyH("CENTER")
	header:SetJustifyV("MIDDLE")
	local drag = CreateFrame("Frame", nil, display)
	drag:SetFrameLevel(display:GetFrameLevel() + 10)
	drag:SetWidth(16)
	drag:SetHeight(16)
	drag:SetPoint("BOTTOMRIGHT", display, -1, 1)
	drag:EnableMouse(true)
	drag:SetScript("OnMouseDown", onDragHandleMouseDown)
	drag:SetScript("OnMouseUp", onDragHandleMouseUp)
	drag:SetAlpha(0.5)
	local tex = drag:CreateTexture(nil, "BACKGROUND")
	tex:SetTexture("Interface\\AddOns\\Wheel\\Textures\\draghandle")
	tex:SetWidth(16)
	tex:SetHeight(16)
	tex:SetBlendMode("ADD")
	tex:SetPoint("CENTER", drag)
	display:SetScript("OnSizeChanged", onResize)
	display:SetScript("OnDragStart", onDragStart)
	display:SetScript("OnDragStop", onDragStop)
	display:SetScript("OnMouseUp", function(self, button)
		if button ~= "LeftButton" then return end
--		plugin:SendMessage("BigWigs_SetConfigureTarget", plugin)
	end)
	display.bars = {}
	display.group = group
	display:Hide()
	
	self.anchor[group] = display
end

function Wheel:ShowAnchor(group)
	if not self.anchor[group] then
		self:CreateAnchor(group)
	end
	self.anchor[group]:Show()
end

function Wheel:HideAnchor(group)
	self.anchor[group]:Hide()
end

function Wheel:ResetAnchors(group)
	local anchor = self.anchor[group]
	local db = self.db.profile.groups[group]
	anchor:ClearAllPoints()
	anchor:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
	db.anchor_x = nil
	db.anchor_y = nil
	db.width = self.db.profile.group_defaults.width
	anchor:SetWidth(db.width)
end

function Wheel:ResetAnchors()
	for group in pairs(self.anchor) do
		self:ResetAnchor(group)
	end
end

function Wheel:UpdateAnchor(group)
	local anchor = self.anchor[group]
	local db = self.db.profile.groups[group]
	if db.anchor_x and db.anchor_y then
		local s = anchor:GetEffectiveScale()
		anchor:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", db.anchor_x / s, db.anchor_y / s)
	else
		anchor:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
	end
	anchor:SetWidth(db.width or 200)
end

function Wheel:StartBar(group, spellID, sourceGUID, sourceName, targetGUID, targetName, duration, rule_index)
	local spell, _, icon = GetSpellInfo(spellID)
	local barname = group.."-"..spellID.."-"..sourceName.."-"..targetName

	local generaldb = self.db.profile.general
	local db = self.db.profile.groups[group]
	
	local bar = Candy:New(LSM:Fetch("statusbar", generaldb.texture), db.width, db.height)
	local anchor = self.anchor[group]

	anchor.bars[bar] = true

	local c
	if db.colour_type == "source" then
		c = RAID_CLASS_COLORS[GUID:GetClass(sourceGUID)]
	elseif db.colour_type == "target" then
		c = RAID_CLASS_COLORS[GUID:GetClass(targetGUID)]
	else
		c = generaldb.colour
	end

--	bar.candyBarBackground:SetVertexColor(c.r, c.g, c.b, 1.00)
	bar:SetColor(c.r, c.g, c.b, 1.00)

	local label = db.label
	label = string.gsub(label, "$c", sourceName)
	label = string.gsub(label, "$t", targetName)
	label = string.gsub(label, "$s", spell)
	bar:SetLabel(label)

	bar:Set("wheel:anchor", anchor)
	bar:Set("wheel:barname", barname)
	bar:Set("wheel:group", group)
	bar:Set("wheel:spellid", spellID)
	bar:Set("wheel:source", sourceName)
	bar:Set("wheel:target", targetName)
	bar:Set("wheel:rule_index", rule_index)
	bar.candyBarLabel:SetTextColor(1, 1, 1, 1)
	bar.candyBarLabel:SetJustifyH("LEFT")
	bar.candyBarLabel:SetFont(LSM:Fetch("font", generaldb.font), db.fontsize)
	bar.candyBarDuration:SetFont(LSM:Fetch("font", generaldb.font), db.fontsize)
	bar:SetClampedToScreen(true)
	bar:SetDuration(duration)
	bar:SetTimeVisibility(true)
	bar:SetIcon(icon)
	bar:SetScale(db.scale)
	bar:Start()
	rearrangeBars(anchor)


--	self:ScheduleTimer("ReminderIcon", 5, "testarg1", "testarg2")
end

function Wheel:StopBar(group, spellID, sourceName, targetName)
	local barname = group.."-"..spellID.."-"..sourceName.."-"..targetName
	local anchor = self.anchor[group]
	local dirty = nil

	for k in pairs(anchor.bars) do
		if k:Get("wheel:barname") == barname then
			k:Stop()
			dirty = true
		end
	end

	if dirty then
		rearrangeBars(anchor)
	end
end

function Wheel:RefreshBar(group, spellID, sourceGUID, sourceName, targetGUID, targetName, duration, index)
	self:StopBar(group, spellID, sourceName, targetName)
	self:StartBar(group, spellID, sourceGUID, sourceName, targetGUID, targetName, duration, index)
end

function Wheel:ReminderIcon(arg1, arg2)
	print(arg1)
end

function Wheel:BarStopped(event, bar)
	local anchor = bar:Get("wheel:anchor")
	if anchor and anchor.bars and anchor.bars[bar] then
--[[		print("BarStopped: "..bar:Get("wheel:barname"))
		local spellid = bar:Get("wheel:spellid")
		if spellid == "53601" then
			print(spellid)
			self:Test1()
		elseif spellid == "53563" then
			print(spellid)
			self:Test2()
		end
]]
		anchor.bars[bar] = nil
		rearrangeBars(anchor)
	end
end

function Wheel:ApplySettings(group)
	local anchor = self.anchor[group]
	local generaldb = self.db.profile.general
	local db = self.db.profile.groups[group]

	local label
	local c
	for bar in pairs(anchor.bars) do

		if db.colour_type == "source" then
			c = RAID_CLASS_COLORS[GUID:GetClass(sourceGUID)]
		elseif db.colour_type == "target" then
			c = RAID_CLASS_COLORS[GUID:GetClass(targetGUID)]
		else
			c = generaldb.colour
		end

--		bar.candyBarBackground:SetVertexColor(c.r, c.g, c.b, 1.00)
		bar:SetColor(c.r, c.g, c.b, 1.00)

--		label = db.label
--		label = string.gsub(label, "$c", bar:Get("wheel:source"))
--		label = string.gsub(label, "$t", bar:Get("wheel:target"))
--		label = string.gsub(label, "$s", GetSpellInfo(tonumber(bar:Get("wheel:spellid"))))
--		bar:SetLabel(label)

		bar.candyBarLabel:SetFont(LSM:Fetch("font", generaldb.font), db.fontsize)
		bar.candyBarDuration:SetFont(LSM:Fetch("font", generaldb.font), db.fontsize)
	end

	if db.lock then
		anchor:Show()
	else
		anchor:Hide()
	end
end

---------------
--   Pulse   --
---------------

local pulse


local throttle_pulse = 0
local function OnUpdate(this, elapsed)
	throttle_pulse = throttle_pulse + elapsed
	if throttle_pulse > 0.05 then
		Wheel:PulseUpdate()
		throttle_pulse = 0
	end
end

function Wheel:CreatePulse()
	local frame = CreateFrame("Frame", "WheelPulse", UIParent)
	frame.icon = frame:CreateTexture(nil, "BACKGROUND")
	frame.icon:SetAllPoints()
	frame.icon:SetTexCoord(0.07, 0.93, 0.07, 0.93)
	frame:Hide()
	
	pulse = frame
	pulse.start = 0
	pulse.duration = 0
end

function Wheel:NewPulse(icon)
	-- update position too, for the "interactive" options
	local db = self.db.profile.pulse
	pulse:SetPoint("CENTER", UIParent, db.x, db.y)
	pulse.start = GetTime()
	pulse.duration = db.duration

	pulse.icon:SetTexture(icon)
	pulse:SetWidth(db.max_width)
	pulse:SetHeight(db.max_width)
	pulse:SetAlpha(1)

	pulse:SetScript("OnUpdate", OnUpdate)

	pulse:Show()
end

function Wheel:PulseUpdate()
	local current = GetTime() - pulse.start
	if current > pulse.duration then
		pulse:Hide()
		pulse:SetScript("OnUpdate", nil)
		return
	end
	
	-- last 1s pulse
	---[[
	local db = self.db.profile.pulse
	if (pulse.duration - current) < 1 then
		current = pulse.duration - current
		local size = db.min_width + (db.max_width - db.min_width) * current
		pulse:SetWidth(size)
		pulse:SetHeight(size)
		pulse:SetAlpha(current)
	end
end

function Wheel:Test1()
	self:NewPulse("Interface\\Icons\\ability_paladin_beaconoflight")
end

function Wheel:Test2()
	self:NewPulse("Interface\\Icons\\ability_paladin_blessedmending")
end

-------------------
--   Announces   --
-------------------

--[[function Wheel:InitializeAnnounce(name)
	local db = self.db.profile

	if not db.announces[spellid] then
		db.announces[spellid] = {}
	end

--	db[spellid] = copyTable(db[spelid], db.general)

--	for k, v in pairs(db.general) do
--		if not db[spellid][k] then
--			db[spellid][k] = v
--		end
--	end

	local spellid = name

	addAnnounceOptions(spellid, name)
end

function Wheel:GetChatChannelIndex(name)
	local index

	local channel_list = GetChannelList()
	for k, v in pairs(channel_list) do
		if v == name then
			-- FIXME: should I just return here?
			index = k
			break
		end
	end

	return index
end

function Wheel:IsServerChannel(channel)
	local server_channels = EnumerateServerChannels()

	local found
	for k, v in pairs(server_channels) do
		if v == channel then
			-- FIXME: should I just return here?
			found = true
			break
		end
	end

	return found
end

function Wheel:GetCustomChannelList()
	local all_channels = GetChannelList()
	local channels = {}

	for k, v in pairs(all_channels) do
		if not self:IsServerChannel(v) then
			channels[v] = v
		end
	end

	return channels
end
]]

